package dimension.starry.player;

import dimension.starry.constants.PlayerDataType;
import dimension.starry.constants.WeaponAttribute;
import dimension.starry.dataManager.PlayerDataManager;
import dimension.starry.gui.Particle.DamageParticle;
import dimension.starry.item.typeInterface.ArmorType;
import dimension.starry.item.typeInterface.WeaponType.WeaponType;
import dimension.starry.utils.RandomUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;

import java.util.Map;

public class ComputedPlayerInfo {

    public static float changeDamage(LivingEntity livingEntity, DamageSource damageSource, float damage) {
        if (damage == 0 || !livingEntity.canTakeDamage()) {
            return damage;
        }
        Entity trueSource = damageSource.getAttacker();
        if (trueSource instanceof PlayerEntity player) {
            boolean isCritical = isCritical(player);
            damage = (float) (isCritical ? getDamage(player) * (getCriticalDamage(player) + 1) : getDamage(player));
            DamageParticle.showParticle(livingEntity, damageSource, damage, isCritical);
            return damage;
        } else if (trueSource instanceof ProjectileEntity projectileEntity) {
            if (projectileEntity.getOwner() instanceof PlayerEntity player) {
                boolean isCritical = isCritical(player);
                damage = (float) (isCritical ? getDamage(player) * (getCriticalDamage(player) + 1) : getDamage(player));
                DamageParticle.showParticle(livingEntity, damageSource, damage, isCritical);
                return damage;
            } else if (projectileEntity.getOwner() instanceof HostileEntity hostileEntity &&
                livingEntity instanceof PlayerEntity player) {
                double attackDamage = hostileEntity.getAttributeBaseValue(EntityAttributes.GENERIC_ATTACK_DAMAGE);
                return (float) (attackDamage - getDefence(player));
            }
        } else if (livingEntity instanceof PlayerEntity player) {
            return damage - (float) getDefence(player);
        }
        return damage;
    }

    private static boolean isCritical(PlayerEntity player) {
        int random = RandomUtil.randomInt(1, 100);
        return random < (int) (getCriticalChance(player) * 100);
    }

    public static float getDamage(PlayerEntity player) {
        double originDamage = 1;
        double damageMultipy = 1;
        ItemStack itemInMainHand = player.getStackInHand(Hand.MAIN_HAND);
        if (!itemInMainHand.isEmpty() && itemInMainHand.getItem() instanceof WeaponType) {
            for (Map.Entry<WeaponAttribute, Double> entry : WeaponType.getAttributeMap(itemInMainHand).entrySet()) {
                if (entry.getKey().equals(WeaponAttribute.BIG_DAMAGE)) {
                    damageMultipy = damageMultipy + entry.getValue();
                } else if (entry.getKey().equals(WeaponAttribute.SMALL_DAMAGE)) {
                    originDamage = originDamage + entry.getValue();
                }
            }
        }
        for (ItemStack itemStack : player.getArmorItems()) {
            if (itemStack.getItem() instanceof ArmorType armorType) {
                if (WeaponAttribute.BIG_DAMAGE.equals(ArmorType.getMainAttribute(itemStack))) {
                    damageMultipy += ArmorType.getMainAttributeValue(itemStack);
                } else if (WeaponAttribute.SMALL_DAMAGE.equals(ArmorType.getMainAttribute(itemStack))) {
                    originDamage += ArmorType.getMainAttributeValue(itemStack);
                }
                for (Map.Entry<WeaponAttribute, Double> entry : ArmorType.getAttributeMap(itemStack).entrySet()) {
                    if (entry.getKey().equals(WeaponAttribute.BIG_DAMAGE)) {
                        damageMultipy = damageMultipy + entry.getValue();
                    } else if (entry.getKey().equals(WeaponAttribute.SMALL_DAMAGE)) {
                        originDamage = originDamage + entry.getValue();
                    }
                }
            }
        }
        originDamage += PlayerDataManager.getInt(player, PlayerDataType.STRENGTH) * 2;

        return (float) (originDamage * damageMultipy);
    }

    public static double getDefence(PlayerEntity player) {
        double originDefence = 1;
        double defenceMultipy = 1;
        ItemStack itemInMainHand = player.getStackInHand(Hand.MAIN_HAND);
        if (!itemInMainHand.isEmpty() && itemInMainHand.getItem() instanceof WeaponType) {
            for (Map.Entry<WeaponAttribute, Double> entry : WeaponType.getAttributeMap(itemInMainHand).entrySet()) {
                if (entry.getKey().equals(WeaponAttribute.BIG_DEFENSE)) {
                    defenceMultipy = defenceMultipy + entry.getValue();
                } else if (entry.getKey().equals(WeaponAttribute.SMALL_DEFENSE)) {
                    originDefence = originDefence + entry.getValue();
                }
            }
        }
        for (ItemStack itemStack : player.getArmorItems()) {
            if (WeaponAttribute.BIG_DEFENSE.equals(ArmorType.getMainAttribute(itemStack))) {
                defenceMultipy += ArmorType.getMainAttributeValue(itemStack);
            } else if (WeaponAttribute.SMALL_DEFENSE.equals(ArmorType.getMainAttribute(itemStack))) {
                originDefence += ArmorType.getMainAttributeValue(itemStack);
            }
            if (itemStack.getItem() instanceof ArmorType) {
                for (Map.Entry<WeaponAttribute, Double> entry : ArmorType.getAttributeMap(itemStack).entrySet()) {
                    if (entry.getKey().equals(WeaponAttribute.BIG_DEFENSE)) {
                        defenceMultipy = defenceMultipy + entry.getValue();
                    } else if (entry.getKey().equals(WeaponAttribute.SMALL_DEFENSE)) {
                        originDefence = originDefence + entry.getValue();
                    }
                }
            }
        }
        originDefence += PlayerDataManager.getInt(player, PlayerDataType.STRONG) * 2;
        return originDefence * defenceMultipy;
    }

    public static long getMagicRegen(PlayerEntity player) {
        long originRegen = 1;
        originRegen += PlayerDataManager.getInt(player, PlayerDataType.WISDOM) * 2L;

        return originRegen;
    }

    public static double getCriticalChance(PlayerEntity player) {
        double originCritChance = 0;
        for (ItemStack itemStack : player.getArmorItems()) {
            if (WeaponAttribute.CRITICAL_CHANCE.equals(ArmorType.getMainAttribute(itemStack))) {
                originCritChance += ArmorType.getMainAttributeValue(itemStack);
            }
            if (itemStack.getItem() instanceof ArmorType armorType) {
                for (Map.Entry<WeaponAttribute, Double> entry : ArmorType.getAttributeMap(itemStack).entrySet()) {
                    if (entry.getKey().equals(WeaponAttribute.CRITICAL_CHANCE)) {
                        originCritChance += entry.getValue();
                    }
                }
            }
        }
        originCritChance += PlayerDataManager.getInt(player, PlayerDataType.ANALYSIS) * 2;

        return originCritChance;
    }

    public static double getCriticalDamage(PlayerEntity player) {
        double originCritDamage = 0.5;
        for (ItemStack itemStack : player.getArmorItems()) {
            if (WeaponAttribute.CRITICAL_DAMAGE.equals(ArmorType.getMainAttribute(itemStack))) {
                originCritDamage += ArmorType.getMainAttributeValue(itemStack);
            }
            if (itemStack.getItem() instanceof ArmorType armorType) {
                for (Map.Entry<WeaponAttribute, Double> entry : ArmorType.getAttributeMap(itemStack).entrySet()) {
                    if (entry.getKey().equals(WeaponAttribute.CRITICAL_DAMAGE)) {
                        originCritDamage += entry.getValue();
                    }
                }
            }
        }
        originCritDamage += PlayerDataManager.getInt(player, PlayerDataType.FLEXIBLE) * 0.05;

        return originCritDamage;
    }

    public static double getMaxHealth(PlayerEntity player) {
        double originHealth = 20;
        double healthMultipy = 1;
        ItemStack itemInMainHand = player.getStackInHand(Hand.MAIN_HAND);
        if (!itemInMainHand.isEmpty() && itemInMainHand.getItem() instanceof WeaponType) {
            for (Map.Entry<WeaponAttribute, Double> entry : WeaponType.getAttributeMap(itemInMainHand).entrySet()) {
                if (entry.getKey().equals(WeaponAttribute.BIG_HEALTH)) {
                    healthMultipy = healthMultipy + entry.getValue();
                } else if (entry.getKey().equals(WeaponAttribute.SMALL_HEALTH)) {
                    originHealth = originHealth + entry.getValue();
                }
            }
        }
        for (ItemStack itemStack : player.getArmorItems()) {
            if (WeaponAttribute.BIG_HEALTH.equals(ArmorType.getMainAttribute(itemStack))) {
                healthMultipy += ArmorType.getMainAttributeValue(itemStack);
            } else if (WeaponAttribute.SMALL_HEALTH.equals(ArmorType.getMainAttribute(itemStack))) {
                originHealth += ArmorType.getMainAttributeValue(itemStack);
            }
            if (itemStack.getItem() instanceof ArmorType) {
                for (Map.Entry<WeaponAttribute, Double> entry : ArmorType.getAttributeMap(itemStack).entrySet()) {
                    if (entry.getKey().equals(WeaponAttribute.BIG_HEALTH)) {
                        healthMultipy = healthMultipy + entry.getValue();
                    } else if (entry.getKey().equals(WeaponAttribute.SMALL_HEALTH)) {
                        originHealth = originHealth + entry.getValue();
                    }
                }
            }
        }
        originHealth += PlayerDataManager.getInt(player, PlayerDataType.STRONG) * 2;
        return originHealth * healthMultipy;
    }

    public static double getExpBonus(PlayerEntity player) {
        double originBonus = 1;

        return originBonus;
    }

    public static double getSearchAbility(PlayerEntity player) {
        double originAbility = 1;

        return originAbility;
    }

    public static long getMaxStamina(PlayerEntity player) {
        long originSt = 1000;
        originSt += PlayerDataManager.getInt(player, PlayerDataType.STRONG) * 50L;

        return originSt;
    }

}
